<!-- 上传组件 -->
<template>
  <view class="uploader">
    <van-uploader
      :file-list="fileList"
      :deletable="deletable"
      :disabled="disabled"
      @afterRead="afterRead"
      @delete="deleteImg"
      :multiple="true"
      :max-count="maxCount"
      :upload-icon="uploadIcon"
      :preview-image="previewImage"
    ></van-uploader>
    <template v-for="(item, index) in originFile">
      <canvas
        v-if="item.show"
        :key="index"
        :canvas-id="`canvas${index}`"
        class="canvas"
        :style="'width:' + item.cWidth + 'px;height:' + item.cHeight + 'px'"
      ></canvas>
    </template>
  </view>
</template>

<script>
import { request, filePost } from "@/utils/http.js";
import globalConfig from "@/utils/config.js";

export default {
  props: {
    value: { type: Array },
    // 是否禁用
    disabled: { type: Boolean, default: false },
    deletable: { type: Boolean, default: true },
    // 上传最大张数
    maxCount: { type: Number, default: 4 },
    // 是否上传至oss
    // isUploaderOss: { type: Boolean, default: true },
    // 接受的文件类型, 可选值为all media image file video
    accept: { type: String, default: "image" },
    uploadUrl: { type: String, default: "/ri/rightsPay/uploadImg" },
    uploadData: { type: Object, default: () => ({}) },
    compressMaxSize: { type: Number, default: 300 * 1024 },
    isCompress: { type: Boolean, default: false },
    uploadIcon: { type: String, default: "plus" },
    previewSize: { type: [Number, String], default: "80px" },
    previewImage: { type: Boolean, default: true },
    ossActionUrl: String,
    maxMB: {
      // 最大上传大小，以MB为单位
      type: Number,
      default: 5
    }
  },
  data() {
    return {
      baseUrl: globalConfig.microUrl,
      imageUrl: globalConfig.imageUrl,
      getUploadSign: "",
      quality: 0.5,
      fileList: [],
      cWidth: 100,
      cHeight: 100,
      originFile: [],
      showCanvas: false
    };
  },
  watch: {
    value() {
      this.fileList = this.value;
    }
  },
  mounted() {
    this.fileList = this.value;
    console.log("this.fileList !!!!!!!!!!!!", this.fileList);
  },
  methods: {
    getImageInfo(i, index) {
      return new Promise((resolve, reject) => {
        i.canvasId = `canvas${index}`;
        uni.getImageInfo({
          src: i.path,
          success: (res) => {
            i.cWidth = res.width;
            i.cHeight = res.height;
            resolve(i);
          }
        });
      });
    },
    /**
     * 上传文件之后
     */
    async afterRead(event) {
      const { file } = event.detail;
      const files = await this.getFiles(file);
      Promise.all(files).then((res) => {
        uni.hideLoading();
        uni.showLoading({ title: "上传中..." });
        this.uploadImage(res);
      });
    },
    /**
     * 根据条件判断 是否需要压缩
     * @param {*} fileList
     */
    async getFiles(fileList) {
      if (this.isCompress) {
        const list = [];
        const startIndex = Math.max(this.originFile.length, 0);
        for (let i = 0; i < fileList.length; i++) {
          const { cWidth, cHeight, canvasId } = await this.getImageInfo(fileList[i], startIndex + i);
          fileList[i] = { ...fileList[i], cWidth, cHeight, canvasId, show: true };
        }
        this.originFile = [...this.originFile, ...fileList];
        for (let i = 0; i < fileList.length; i++) {
          const res = await this.compressImg(fileList[i], startIndex + i);
          list.push(res);
          this.consoleFile(fileList[i], res.path);
        }
        return list;
      }
      return fileList;
    },

    /**
     * 打印 压缩对比信息
     * @param {} file
     * @param {*} newFile
     */
    consoleFile(file, newFile) {
      const origin = Math.trunc(file.size / 1024);
      const isCompress = this.isCompress && file.size > 1024 * 1024 * this.maxMB;
      wx.getFileSystemManager().getFileInfo({
        filePath: newFile,
        success: (res) => {
          const newSize = Math.trunc(res.size / 1024);
          console.log("是否压缩", isCompress, "原始大小", `${origin}kb`, "，压缩后大小", `${newSize}kb`);
        },
        fail: (e) => {
          console.error("获取文件信息失败", e);
        }
      });
    },
    /**
     * 上传图片
     * @param {上传的文件} file
     */
    uploadImage(file) {
      const uploadTask = file.map((i) => (this.ossActionUrl ? this.uploadOss(i) : this.uploadXL(i)));
      Promise.all(uploadTask)
        .then((res) => {
          this.fileList = this.fileList.concat(res);
          this.$emit("input", this.fileList);
          this.$emit("afterRead", this.fileList);
          console.log("this.fileList", this.fileList);
          uni.hideLoading();
        })
        .catch((err) => {
          // 存在有上传失败的文件
          console.error("存在有上传失败的文件", err);
          uni.hideLoading();
          uni.showToast({ title: "上传失败！", icon: "none" });
        });
    },
    pathToBase64(filePath) {
      return new Promise((resolve, reject) => {
        const res = wx.getFileSystemManager().readFileSync(filePath, "base64");
        res ? resolve(`data:image/jpeg;base64,${res}`) : reject(new Error("获取失败"));
      });
    },
    /**
     * 压缩图片
     * @param {压缩的文件} file
     */
    async compressImg(file) {
      const that = this;
      console.log("compressImg====", file);
      return new Promise(async (resolve, reject) => {
        const { cWidth, cHeight, canvasId } = file;
        const ctx = uni.createCanvasContext(canvasId, that);
        ctx.drawImage(file.path, 0, 0, cWidth, cHeight);
        ctx.draw(
          false,
          setTimeout(() => {
            uni.canvasToTempFilePath(
              {
                canvasId,
                fileType: "jpg",
                quality: this.quality,
                success: (res1) => resolve({ path: res1.tempFilePath }),
                fail: (res) => reject(res.errMsg)
              },
              that
            );
          }, 1000)
        ); // 留一定的时间绘制canvas
      });
    },
    async uploadOss({ path }) {
      const res = await request({ url: this.getUploadSign, method: "GET", data: {} });
      const { host, policy, accessid: OSSAccessKeyId, signature, dir } = res.data;
      // TODO 上传文件名规则待确定
      const fileName = parseInt(Math.random() * 10000) + 1;
      const timestamp = Date.parse(new Date());
      const fileFormat = path.split(".")[1];
      const key = `${dir}${timestamp}_${fileName}.${fileFormat}`;
      return new Promise((resolve, reject) => {
        uni.uploadFile({
          url: host,
          name: "file",
          filePath: path,
          header: { "Content-Type": "multipart/form-data" },
          formData: { key, policy, OSSAccessKeyId, signature, success_action_status: "200" },
          success(res) {
            if (res.statusCode === 200) {
              uni.hideNavigationBarLoading();
              resolve({ url: `${host}/${key}` });
            } else {
              reject();
            }
          },
          fail(res) {
            console.log("上传失败 ", res);
            uni.hideNavigationBarLoading(); // reject(false)
          },
          complete() {
            uni.hideNavigationBarLoading();
          }
        });
      });
    },
    async uploadXL({ path }) {
      const url = this.uploadUrl.indexOf(globalConfig.microUrl) !== -1 ? this.uploadUrl : globalConfig.baseUrl + this.uploadUrl;
      let res = await filePost({ url, filePath: path, data: this.uploadData || {} });
      res = JSON.parse(res);
      return Promise.resolve({ url: this.imageUrl + res.data.filePath, data: res.data });
    },
    /**
     * 删除文件
     */
    deleteImg(event) {
      const delIndex = event.detail.index;
      const fileList = this.fileList;
      fileList.splice(delIndex, 1);
      this.fileList = fileList;
      this.$emit("input", this.fileList);
      // 与原来保持一致
      this.$emit("delete", { detail: { index: delIndex } });
    }
  }
};
</script>
<style lang="scss" scoped>
.uploader {
  position: relative;
  .canvas {
    position: absolute;
    left: -20000px;
    top: -20000px;
  }
}
</style>
